package com.manzuo.framework.log;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.manzuo.framework.reflection.ReflectionUtils;

/**
 * 处理AutoLog注解的AspectJ切面。
 * @see AutoLog
 * @author 高恒
 */
@Aspect
public class AutoLogAspect {

	private static final Logger logger = LoggerFactory
			.getLogger(AutoLogAspect.class);
	
	@SuppressWarnings("unused")
	@Pointcut("@annotation(com.manzuo.framework.log.AutoLog)")
	private void logRequired() {};

	@Around("logRequired()")
	public Object logArround(ProceedingJoinPoint pjp)
			throws Throwable {
		Object target = pjp.getTarget();
		Object value = null;
		Throwable targetThrowable = null;
		System.out.println("in" + pjp.getSignature().getName());
		try {			
			Logger targetLogger = LoggerFactory.getLogger(target.getClass());
			Signature sign = pjp.getSignature();
			
			Method method = ReflectionUtils.getMethod(target, sign.getName(), pjp.getArgs());			
			AutoLog al = method.getAnnotation(AutoLog.class);
			String msg = al.value();
			
			targetLogger.debug(
					"[Starting:{}][Method:{}][args:{}]",
					new Object[] { 
							msg,
							sign.getDeclaringTypeName() + ":" + sign.getName(),
							pjp.getArgs() });
			try {
				value = pjp.proceed();
			} catch (Throwable t) {
				targetLogger.error("[Error][Method:" + sign.getDeclaringTypeName() + ":" + sign.getName() + "]", t);
				targetThrowable = t;
			}
			if(targetThrowable == null) {
				targetLogger.debug(
						"[Finished][Method:{}][args:{}][return:{}]",
						new Object[] { sign.getDeclaringTypeName() + ":" + sign.getName(),
								pjp.getArgs(),
								value });
			}
		} catch(Throwable t) {
			logger.error("Error when auto log!", t);
		}
		if(targetThrowable != null) {
			System.out.println("error" + pjp.getSignature().getName());
			throw targetThrowable;
		}
		System.out.println("out" + pjp.getSignature().getName());
		return value;
	}

}
